package com.manager.commons.encrypt;

//                   _ooOoo_    
//                  o8888888o    
//                  88" . "88    
//                  (| -_- |)    
//                   O\ = /O    
//               ____/'---'\____    
//              /. '\\| : |//' .\    
//             // \\||| : |||// \\   
//            // _|||||-:-|||||_ \\    
//           // | | \\\ - /// | | \\
//           || |_| ''\---/'' |_| || 
//            \ .-\___/'-'\___/-. /    
//          ___\. .' /--.--\ '. ./___    
//        .""'< `.___\_<|>_/___.' >'"".    
//       | |: `- \`.|'\ _ /'|.`/ -` :| |    
//        \ \ `-. \_ __\ /__ _/ .-` / /    
//======'-.___`-.___\_______/___.-`___.-'======    
//                   '=---='    
//.................................................    
//写一哈代码，你就青叫唤；信龟儿设计，你逗是傻逼。
//永无Bug，啷个可能！求佛主保佑也没球用！

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * 密码生成
 * @author H
 * @version V1.0
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class PasswordGenerator {

	public static final char[] allowedSpecialCharactors = { '`', '~', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', '{', '}', ']', '\\', '|', ';', ':', '"', '\'', ',', '<', '.', '>', '/', '?' };

	private static final int letterRange = 26;
	private static final int numberRange = 10;
	private static final int spCharactorRange = allowedSpecialCharactors.length;

	private static final Random random = new Random();

	/**
	 * 密码的长度
	 */
	private final int passwordLength;
	/**
	 * 密码包含字符的最少种类
	 */
	private final int minVariousType;

	/**
	 * 
	 * @param passwordLength
	 * @param minVariousType
	 */
	public PasswordGenerator(int passwordLength, int minVariousType) {
		if (minVariousType > CharactorType.values().length)
			minVariousType = CharactorType.values().length;
		if (minVariousType > passwordLength)
			minVariousType = passwordLength;
		this.passwordLength = passwordLength;
		this.minVariousType = minVariousType;
	}

	/**
	 * 生成随机密码
	 * 
	 * @return
	 */
	public String generateRandomPassword() {
		char[] password = new char[passwordLength];
		List<Integer> pwCharsIndex = new ArrayList<Integer>();
		for (int i = 0; i < password.length; i++) {
			pwCharsIndex.add(i);
		}
		List<CharactorType> takeTypes = new ArrayList(Arrays.asList(CharactorType.values()));
		List<CharactorType> fixedTypes = Arrays.asList(CharactorType.values());
		int typeCount = 0;
		while (pwCharsIndex.size() > 0) {
			int pwIndex = pwCharsIndex.remove(random.nextInt(pwCharsIndex.size()));// 随机填充一位密码
			Character c;
			if (typeCount < minVariousType) {// 生成不同种类字符
				c = generateCharacter(takeTypes.remove(random.nextInt(takeTypes.size())));
				typeCount++;
			} else {// 随机生成所有种类密码
				c = generateCharacter(fixedTypes.get(random.nextInt(fixedTypes.size())));
			}
			password[pwIndex] = c.charValue();
		}
		return String.valueOf(password);
	}

	/**
	 * 生成字符
	 * 
	 * @param type
	 * @return
	 */
	private Character generateCharacter(CharactorType type) {
		Character c = null;
		int rand;
		switch (type) {
		case LOWERCASE:// 随机小写字母
			rand = random.nextInt(letterRange);
			rand += 97;
			c = new Character((char) rand);
			break;
		case UPPERCASE:// 随机大写字母
			rand = random.nextInt(letterRange);
			rand += 65;
			c = new Character((char) rand);
			break;
		case NUMBER:// 随机数字
			rand = random.nextInt(numberRange);
			rand += 48;
			c = new Character((char) rand);
			break;
		case SPECIAL_CHARACTOR:// 随机特殊字符
			rand = random.nextInt(spCharactorRange);
			c = new Character(allowedSpecialCharactors[rand]);
			break;
		}
		return c;
	}

	public static void main(String[] args) {
		System.out.println(new PasswordGenerator(10, 3).generateRandomPassword());
	}
}

enum CharactorType {
	LOWERCASE, UPPERCASE, NUMBER, SPECIAL_CHARACTOR
}